#!/usr/bin/perl

use Net::XMPP qw (Client);
use Chatbot::Eliza;
use Audio::MPD;

# Hash to hold presence info received from Jabber server
# ------------------------------------------------------
use vars qw/%presence/;

# Hash to track "Sessions"
# ------------------------------------------------------
my $session;

# Bot Connection
# ------------------------------------------------------
my $mybot = new Chatbot::Eliza {
    name       => "Brian",
    scriptfile => "./botbrain.txt",
    debug      => 1,
    prompts_on => 1,
    memory_on  => 1,
    myrand     => sub {
        my $N = defined $_[0] ? $_[0] : 1;
        rand( $N );
    },
};

# MPD Connection
# -----------------------------------------------------
my $mpd = new Audio::MPD( 'localhost', 6600 );

# Create a new Jabber client and connect
# --------------------------------------
my $jabconn = Net::XMPP::Client->new();
$jabconn->Connect( "hostname" => "jabber.mauch.name",
                   "port"     => 5222
                 ) or die "Cannot connect ($!)\n";

# Identify and authenticate with the server
# -----------------------------------------
#my @result = $jabconn->AuthSend( "username" => 'charles',
#                                 "password" => 'mau74rf1',
#                                 "resource" => 'Alex' );
my @result = $jabconn->AuthSend( "username" => 'bot',
                                 "password" => 'password',
                                 "resource" => 'Bot'
                               );
if ( $result[0] ne "ok" ) {
    die "Ident/Auth with server failed: $result[0] - $result[1]\n";
}

# Set presence callback
# ---------------------
$jabconn->SetCallBacks( message  => \&handle_message,
                        presence => \&handle_presence );

# Send our presence
# -----------------
$jabconn->RosterGet();

$jabconn->PresenceSend( type     => "available",
                        Status   => "Ready for anything",
                        priority => 1
                      );

# Wait for data, Main Loop
# ----------------------------------------------
while ( defined( $jabconn->Process() ) ) { }

$jabconn->Disconnect();

exit;

sub handle_presence {

    my ( $sid, $presence ) = @_;
    my $jid = $presence->GetFrom();
    $jid =~ s!\/.*$!!;    # remove any resource suffix from JID
    my $show = $presence->GetShow();
    my $type = $presence->GetType();
    logger( "Status: \($jid\) : $show" );
    $present{ $jid } = $show || 'normal';

    if ( $type eq "subscribe" ) {
        $jabconn->Send( $presence->Reply( type => 'subscribed' ) );
        $jabconn->Send( $presence->Reply( type => 'subscribe' ) );
    }
    if ( $type eq "unsubscribe" ) {
        $jabconn->Send( $presence->Reply( type => 'unsubscribed' ) );
        $jabconn->Send( $presence->Reply( type => 'unsubscribe' ) );
    }
} ## end sub handle_presence

sub handle_message {
    my ( $sid, $message ) = @_;
    $type = $message->GetType();
    $user = $message->GetFrom();
    $user = lc( $user );
    $user =~ s/ //g;
    $user =~ s!\/.*$!!;
    $subject = $message->GetSubject();
    $msg     = $message->GetBody();
    $msg =~ s/<(.|\n)+?>//g;
    my ( $shortname, undef ) = split( /@/, $user );
    $shortname =~ tr/a-z/A-Z/;
    logger( "$shortname: $msg" );

    $session->{ $user }, "\n";   # Define a new hash ref, using $user the scalar

    if ( defined( $session->{ $user }->{ 'start' } ) ) {
        if ( $session->{ $user }->{ 'start' } > time - 600 )
        {    # Session times out after 10 minutes of inactivity
            $session->{ $user }->{ 'msgnum' } =
              $session->{ $user }->{ 'msgnum' } + 1;
        } else {
            delete $session->{ $user };
            $session->{ $user }->{ 'start' }  = time;
            $session->{ $user }->{ 'msgnum' } = 1;
        }

        print
          "OLD ID: $session->{$user}, TIME: $session->{$user}->{'start'}, MSGS: $session->{$user}->{'msgnum'}\n";

    } else {
        $session->{ $user }->{ 'start' }  = time;
        $session->{ $user }->{ 'msgnum' } = 1;
        print
          "NEW ID: $session->{$user}, TIME: $session->{$user}->{'start'}, MSGS: $session->{$user}->{'msgnum'}\n";
    }

    if ( $session->{ $user }->{ 'msgnum' } eq 1 ) {
        $reply = generatereply( { user => $user,
                                  msg  => greet
                                }
                              );
    } elsif ( $msg =~ /.*(music|musak|mpd).*/ ) {
        $reply = generatereply( { user => $user,
                                  msg  => music
                                }
                              );
    } else {
        $reply = generatereply( { user => $user,
                                  msg  => $msg
                                }
                              );
    }
    $jabconn->Send( $reply );
} ## end sub handle_message

sub generatereply {
    my ( $args ) = @_;
    my $sleep = int( rand( 10 - 5 + 1 ) ) + 5;

    if ( $args->{ 'msg' } eq "greet" ) {

        $response =
          "Hello there, My legal name is Alexander Perchov, but all of my friends dub me Alex because this is much more flaccid to utter.  My miniature brother, Charles is out getting carnal with women.";
        sleep $sleep;
        print "Sleeping $sleep seconds\n";

    } elsif ( $args->{ 'msg' } eq "music" ) {

        $response =
          "I am currently jamming out to \"" . $mpd->get_title . "\"\n";

    } else {

        $response = $mybot->transform( $args->{ 'msg' } );
        sleep $sleep;
        print "Sleeping $sleep seconds\n";
    }

    $reply = Net::XMPP::Message->new();
    $reply->SetMessage( "to"   => "$args->{'user'}",
                        "type" => "chat",
                        "body" => "$response"
                      );
    logger( "BOT: $response" );
  return $reply;
} ## end sub generatereply

sub logger {
    my $msg = shift;
    open( LOG, ">> bot.log" );
    print LOG ( "$msg\n" );
    close LOG;
}
